package com.ruoyi.project.utils;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import com.ruoyi.common.utils.BASE64DecodedMultipartFile;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import sun.misc.BASE64Decoder;

import javax.annotation.PostConstruct;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;


@Component
public class QiniuUtils {

    private static final Logger log = LoggerFactory.getLogger(QiniuUtils.class);

    @Value ("${qiniu.accessKey}")
    private String accessKey;

    @Value ("${qiniu.secretKey}")
    private String secretKey;

    @Value ("${qiniu.bucket}")
    private String bucket;

    private Auth auth;

    // 创建上传对象
    private UploadManager uploadManager;

    private BucketManager bucketManager;

    @PostConstruct
    public void init () {
        this.auth = Auth.create(this.accessKey, this.secretKey);
        Configuration c = new Configuration(Region.autoRegion());
        this.uploadManager = new UploadManager(c);
        this.bucketManager = new BucketManager(this.auth, c);

    }


    /**
     * 获取七牛upToken
     */
    public String getUpToken () {
        String upToken = this.auth.uploadToken(this.bucket);
        return upToken;
    }

    /**
     * 获取七牛upToken
     * @param pickName 视频名称
     * @return
     */
    public String getUpVideoToken (String pickName,String videoCompressConfig) {
        String saveas ="zlgpt1:"+ pickName;
        String fops=videoCompressConfig;
        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        String urlbase64 = UrlSafeBase64.encodeToString(saveas);
        String pfops = fops + "|saveas/" + urlbase64;

        String upToken = auth.uploadToken(this.bucket, null, 3600,
                new StringMap().putNotEmpty("persistentOps", pfops).putNotEmpty("persistentPipeline","zlgspysdl"), true);
        //String upToken = this.auth.uploadToken(this.bucket);
        return upToken;
    }
    /**
     * 上传邀请码到七牛
     */
    public String uploadQrCode (String content) throws Exception {

        try {
            BufferedImage bufferedImage = QRCodeUtil.codeCreateBufferImage(content, 490, 490);
            if (bufferedImage != null) {
                InputStream inputStream = QRCodeUtil.bufferedImageToInputStream(bufferedImage);
                if (inputStream != null) {
                    //调用put方法上传
                    Response res = this.uploadManager.put(inputStream, null, this.getUpToken(), null, null);
                    if (res.isOK()) {
                        DefaultPutRet putRet = new Gson().fromJson(res.bodyString(), DefaultPutRet.class);
                        return putRet.key;
                    } else {
                        log.error("上传失败" + res.error);
                        throw new RuntimeException("上传失败");
                    }
                } else {
                    log.error("邀请码流转换异常");
                    throw new RuntimeException("邀请码流转换异常");
                }

            } else {
                log.error("生成邀请二维码异常");
                throw new RuntimeException("邀请码流转换异常");
            }

        } catch (QiniuException e) {
            // 请求失败时打印的异常的信息
            Response r = e.response;
            log.error("七牛异常:" + r.toString());
            throw new RuntimeException("七牛异常");
        }
    }

    /**
     * 上传图片到七牛
     */
    public String uploadImage (MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        if (inputStream != null) {
            //调用put方法上传
            Response res = this.uploadManager.put(inputStream, null, this.getUpToken(), null, null);
            if (res.isOK()) {
                DefaultPutRet putRet = new Gson().fromJson(res.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }
        }
        return null;
    }

    /**
     * 上传视频到七牛
     */
    public String uploadVideo (MultipartFile file,String videoCompressConfig) throws Exception {
        InputStream inputStream = file.getInputStream();
        if (inputStream != null) {

            String videoName = "video"+SnowFlakeUtil.getDefaultSnowFlakeId();
            //调用put方法上传
            Response res = this.uploadManager.put(inputStream, null, this.getUpVideoToken(videoName,videoCompressConfig), null, null);
            if (res.isOK()) {
                return videoName;
            }
        }
        return null;
    }
    /**
     * 上传图片到七牛
     */
    public String uploadFile (MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        if (inputStream != null) {
            //调用put方法上传
            Response res = this.uploadManager.put(inputStream, null, this.getUpToken(), null, null);
            if (res.isOK()) {
                DefaultPutRet putRet = new Gson().fromJson(res.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }
        }
        return null;
    }

    /**
     * 上传图片到七牛
     */
    public String uploadFile (String filePath) throws Exception {
        File file = new File(filePath);
        FileInputStream inputStream = new FileInputStream(file);
        if (inputStream != null) {
            //调用put方法上传
            Response res = this.uploadManager.put(inputStream, null, this.getUpToken(), null, null);
            if (res.isOK()) {
                DefaultPutRet putRet = new Gson().fromJson(res.bodyString(), DefaultPutRet.class);
                return putRet.key;
            }
        }
        return null;
    }

    // 七牛云删除文件
    public boolean delete (String fileKey) {
        try {
            this.bucketManager.delete(this.bucket, fileKey);
            return true;
        } catch (QiniuException e) {
            //如果遇到异常，说明删除失败
            log.error("七牛异常:" + e.response.toString());
            return false;
        }
    }

    // 批处理删除文件
    public boolean batchDelete (List <String> fileKeys) {
        BucketManager.BatchOperations operations = new BucketManager.BatchOperations();
        for (String fileKey : fileKeys) {
            operations.addDeleteOp(this.bucket, fileKey);
        }
        try {
            this.bucketManager.batch(operations);
            return true;
        } catch (QiniuException e) {
            log.error("文件删除错误", e.response.toString());
            return false;
        }
    }

    public MultipartFile base64ToMultipartFile (String s) {
        MultipartFile image = null;
        StringBuilder base64 = new StringBuilder("");
        if (s != null && !"".equals(s)) {
            base64.append(s);
            String[] baseStrs = base64.toString().split(",");
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            try {
                b = decoder.decodeBuffer(baseStrs[1]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            for (int j = 0; j < b.length; ++j) {
                if (b[j] < 0) {
                    b[j] += 256;
                }
            }
            image = new BASE64DecodedMultipartFile(b, baseStrs[0]);
        }
        return image;
    }



    public static void main (String[] args) throws IOException {
        Auth auth = Auth.create("Kifwp7tMRiLPPgia_hh4Oarj8z_JnHEkaM5p43Ll", "4g1detUUiLaeRmqI5FrFEXzVUI-0MiwmnxghVSZG");
/*
        String zlgpt1 = auth.uploadToken("zlgpt1", null, 3600,
                new StringMap().putNotEmpty("persistentOps", "avthumb/mp4/s/640x360/vb/1" +
                        ".25m|saveas/emxncHQxOnZpZGVvMDEubXA0").putNotEmpty("persistentPipeline","zlgspysdl"), true);*/
        String saveas ="zlgpt1:"+ UUID.randomUUID() +".mp4";
        String fops="avthumb/mp4/s/640x360/vb/1.25m";
        System.out.println(saveas);
        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        String urlbase64 = UrlSafeBase64.encodeToString(saveas);
        String pfops = fops + "|saveas/" + urlbase64;

        String zlgpt1 = auth.uploadToken("zlgpt1", null, 3600,
                new StringMap().putNotEmpty("persistentOps", pfops).putNotEmpty("persistentPipeline","zlgspysdl"), true);

        File fie = new File("D:\\file\\video00000.mp4");
        MultipartFile multipartFile= fileToMultipartFile(fie);
        System.out.println(zlgpt1);
        //调用put方法上传
        InputStream inputStream = multipartFile.getInputStream();
        if (inputStream != null) {
            //调用put方法上传
            Configuration c = new Configuration(Region.autoRegion());
            UploadManager uploadManager = new UploadManager(c);
            Response res = uploadManager.put(inputStream, null, zlgpt1, null, null);
            if (res.isOK()) {
                DefaultPutRet putRet = new Gson().fromJson(res.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
            }
        }


    }


    /**
     * 文件转换
     * @param file
     * @return
     */
    public static MultipartFile fileToMultipartFile (File file) {
        FileItem fileItem = createFileItem(file);
        MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
        return multipartFile;
    }

    private static FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }
}
